﻿namespace NHibernate.Sidekick.Data.Domain
{
    /// <summary>
    /// Reference type for the DomainObject.
    /// </summary>
    public interface IDomainObject<TId>
    {
        /// <summary>
        /// The object's identifier.
        /// </summary>
        TId Id { get; set; }
    }

    /// <summary>
    /// Conceptual model of the specified entity.
    /// </summary>
    /// <typeparam name="T">The type of domain object</typeparam>
    /// <typeparam name="TId">The type of the identifier.</typeparam>
    public abstract class DomainObject<T, TId> : IDomainObject<TId> where T : class 
    {
        /// <summary>
        /// The object's identifier.
        /// </summary>
        public virtual TId Id { get; set; }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            var toCompare = obj as T;

            return toCompare == null
                       ? false
                       : (GetHashCode() == toCompare.GetHashCode());
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            var hashCode = 0;
            hashCode = hashCode ^ Id.GetHashCode();
            return hashCode;
        }
    }
}